package com.martini.satoken01.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.martini.satoken01.model.AjaxJson;
import com.martini.satoken01.model.domain.QrLoginInfoDO;
import com.martini.satoken01.service.LoginInfoCacheService;
import com.martini.satoken01.service.system.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author martini at 2021/12/18 14:39
 */
@Slf4j
@RestController
@RequestMapping("/qrcode")
public class CaptchaController {

    @Value("${qrcode.login.force-protocol:#{null}}")
    private String forceProtocol;

    @Value("${qrcode.login.timeout:300000}")
    private long timeout;

    @Value("${qrcode.login.host:localhost}")
    private String host;

    @Value("${qrcode.login.port:8080}")
    private int port;

    private final LoginInfoCacheService loginInfoCacheService;

    public CaptchaController(LoginInfoCacheService loginInfoCacheService) {
        this.loginInfoCacheService = loginInfoCacheService;
    }

    /**
     * 登录二维码接口，此处我们需要返回给前端以下几个部分
     * 1. qr: 二维码base64, [包含]二维码扫描注册接口地址
     * 2. key: pc端轮询需要以此key寻找value判断是否有信息，
     *         注意需要使用{@link com.martini.satoken01.service.system.UserService#getQrLoginInfoKey(String)}
     *         获取到后端缓存的真实key
     * 3. checkUrl: 检查状态接口地址
     * 4. loginUrl: 二维码登录接口地址
     * 5. qrTimeout: 二维码超时之后的base64(二维码颜色变换)
     * 6. timeout: 超时时间
     *
     * 缓存结构参考: {@link com.martini.satoken01.model.domain.QrLoginInfoDO}
     *
     * @return {@link AjaxJson}
     */
    @GetMapping("/login")
    public AjaxJson getLoginQrcode(@RequestHeader("User-Agent") String uaStr) {
        String key = IdUtil.fastSimpleUUID();
        String protocol = this.forceProtocol != null ? this.forceProtocol + ":" : "";
        String checkUrl = protocol + "//" + this.host + ":" + this.port + "/login/qrCheck?key=" + key;
        String qrInfo = protocol + "//" + this.host + ":" + this.port + "/login/qr?key=" + key;
        String loginUrl = protocol + "//" + this.host + ":" + this.port + "/login/byQr?key=" + key;

        QrConfig activeQrConfig = new QrConfig();
        activeQrConfig.setWidth(256);
        activeQrConfig.setHeight(256);
        String qrBase64 = QrCodeUtil.generateAsBase64(qrInfo, activeQrConfig, "jpg");

        QrConfig timeoutQrConfig = new QrConfig();
        timeoutQrConfig.setWidth(256);
        timeoutQrConfig.setHeight(256);
        timeoutQrConfig.setForeColor(Color.GRAY);
        String timeoutQrBase64 = QrCodeUtil.generateAsBase64(qrInfo, timeoutQrConfig, "jpg");

        // 缓存中添加数据
        UserAgent ua = UserAgentUtil.parse(uaStr);
        QrLoginInfoDO qrLoginInfoDO = new QrLoginInfoDO();
        qrLoginInfoDO.setScanned(false);
        qrLoginInfoDO.setWaitingDevice(ua.getPlatform().toString());
        loginInfoCacheService.put(UserService.getQrLoginInfoKey(key), qrLoginInfoDO, this.timeout, TimeUnit.MILLISECONDS);

        Map<String, Object> data = new HashMap<>(4);
        data.put("key", key);
        data.put("checkUrl", checkUrl);
        data.put("loginUrl", loginUrl);
        data.put("qr", qrBase64);
        data.put("qrTimeout", timeoutQrBase64);
        data.put("timeout", timeout);
        return AjaxJson.success().setData(data);
    }
}
